/* Author: YangSaqing
 * Last edit:2019-03-07
 *
 */

#include "pdxp.h"
#include <QString>
#include <QDate>
#include <QTime>
#include <stdarg.h>
Pdxp::Pdxp(QObject *parent):QUdpSocket(parent)
{
}
Pdxp::~Pdxp()
{
}
void PdxpHead::setOpt(HeadFlag opt, const unsigned int &value)
{
    switch (opt) {
    case VER:
        memcpy(mHeader+opt,&value,1);
        break;
    case MID:
        memcpy(mHeader+opt,&value,2);
        break;
    case SID:
        memcpy(mHeader+opt,&value,4);
        break;
    case DID:
        memcpy(mHeader+opt,&value,4);
        break;
    case BID:
        memcpy(mHeader+opt,&value,4);
        break;
    case No:
        memcpy(mHeader+opt,&value,4);
        break;
    case FLAG:
        memcpy(mHeader+opt,&value,1);
        break;
    case Reserve:
        memcpy(mHeader+opt,&value,4);
        break;
    case DATE:
        memcpy(mHeader+opt,&value,2);
        break;
    case TIME:
        memcpy(mHeader+opt,&value,4);
        break;
    case Length:
        memcpy(mHeader+opt,&value,2);
        break;
    default:
        return;
    }
}
unsigned int PdxpHead::getOpt(HeadFlag opt) const
{
    unsigned int value = 0;
    switch (opt) {
    case VER:
        memcpy(&value,mHeader+opt,1);
        break;
    case MID:
        memcpy(&value,mHeader+opt,2);
        break;
    case SID:
        memcpy(&value,mHeader+opt,4);
        break;
    case DID:
        memcpy(&value,mHeader+opt,4);
        break;
    case BID:
        memcpy(&value,mHeader+opt,4);
        break;
    case No:
        memcpy(&value,mHeader+opt,4);
        break;
    case FLAG:
        memcpy(&value,mHeader+opt,1);
        break;
    case Reserve:
        memcpy(&value,mHeader+opt,4);
        break;
    case DATE:
        memcpy(&value,mHeader+opt,2);
        break;
    case TIME:
        memcpy(&value,mHeader+opt,4);
        break;
    case Length:
        memcpy(&value,mHeader+opt,2);
        break;
    default:
        return 0;
    }
    return value;
}
char* PdxpHead::data()
{
    return mHeader;
}
int Pdxp::readPdxp(PdxpHead *head, char *data, const unsigned int &maxLength, QHostAddress *addr, quint16 *port)
{

    int udpSize = pendingDatagramSize();
    //PDXP's header is 32 bytes
    if(udpSize < 32)
    {
        return -1;
    }
    char *udpData = new char[udpSize];
    readDatagram(udpData,udpSize,addr,port);
    memcpy(head->data(),udpData,32);

    if(maxLength<(unsigned int)(udpSize-32))
    {
        memcpy(data,udpData+32,maxLength);
        delete [] udpData;
    }else
    {
        memcpy(data,udpData+32,udpSize-32);
        delete [] udpData;
    }


    return udpSize-32;
}


bool Pdxp::sendPdxp(PdxpHead &head, const char *data, const QHostAddress &add, const quint16 &port)
{
    if(!data)
        return false;
    quint16 dataL = head.getOpt(PdxpHead::Length);
    char *udpData = new char[dataL+32];
    QDate currentDate = QDate::currentDate();
    QDate startDate(2000,1,1);
    head.setOpt(PdxpHead::DATE,startDate.daysTo(currentDate)+1);

    QTime currentTime = QTime::currentTime();
    head.setOpt(PdxpHead::TIME,currentTime.msecsSinceStartOfDay()*10);

    memcpy(udpData,head.data(),32);
    memcpy(udpData+32,data,dataL);
    head.setOpt(PdxpHead::No,head.getOpt(PdxpHead::No)+1);
    this->writeDatagram(udpData,dataL+32,add,port);
    delete []udpData;
    return true;
}

QString PdxpHead::inf() const
{
    quint8 ver = getOpt(VER);
    quint16 mid = getOpt(MID);
    quint32 sid = getOpt(SID),did = getOpt(DID),bid = getOpt(BID);
    quint32 no = getOpt(No);
    quint8 flag = getOpt(FLAG);
    quint32 reserve = getOpt(Reserve);
    quint16 date = getOpt(DATE);
    QDate pdxpDate(QDate(2000,1,1).addDays(date-1));
    quint32 time = getOpt(TIME);
    QTime pdxpTime(QTime(0,0,0,0).addMSecs(time/10));
    quint16 L = getOpt(Length);
    QString str;
    str.append("VER(1):"+QString::number(ver,16)+", MID(2):"+QString::number(mid,16)+", SID(4):"+
               QString::number(sid,16)+", DID(4):"+QString::number(did,16)+", BID(4):"+
               QString::number(bid,16)+", No(4):"+QString::number(no,16)+", flag(1):"+
               QString::number(flag,16)+", reserve(4):"+QString::number(reserve,16)+", DATE(2):"+
               QString::number(date,16)+"("+pdxpDate.toString("yyyy-MM-dd")+"), TIME(4):"+
               QString::number(time,16)+"("+pdxpTime.toString("hh:mm:ss:zzz")+"),L(2):"+QString::number(L,16));
    return str;
}
